﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.Collections;
using System.Runtime.Serialization;
using System.Xml;

namespace SharpML.Api.Types
{
    [Serializable]
    public class XmlSerializableDictionary<KeyType, ValueType> : Dictionary<KeyType, ValueType>, IXmlSerializable
        where KeyType : class
        where ValueType : class
    {
        #region - Construction -

            public XmlSerializableDictionary() : this( (IEqualityComparer<KeyType>)StringComparer.InvariantCultureIgnoreCase ) { }

            public XmlSerializableDictionary( IEqualityComparer<KeyType> comparer ) : base( comparer ) { }

        #endregion

        #region - IXmlSerializable Implementation -

            public System.Xml.Schema.XmlSchema GetSchema()
            {
                return null;
            }

            public void ReadXml( System.Xml.XmlReader reader )
            {
                if( reader.IsEmptyElement )
                {
                    reader.Read();
                    return;
                }

                //try
                //{
                //    this.Add( "Name" as KeyType, reader.Name as ValueType );
                //}
                //finally
                //{
                //    reader.Read();
                //}

                while( reader.NodeType != System.Xml.XmlNodeType.EndElement )
                {
                    KeyType nameKey = reader.Name as KeyType;
                    if( nameKey != default( KeyType ) )
                    {
                        ValueType @value = reader.ReadString() as ValueType;
                        if( @value != default( ValueType ) )
                            this.Add( nameKey, @value );
                        else
                            throw new NullReferenceException( "null data in serialization stream" );

                    }
                    if( !reader.Read() )
                        break;
                }

                reader.ReadEndElement();

            }

            public void WriteXml( System.Xml.XmlWriter writer )
            {
                XmlSerializableDictionary<KeyType, ValueType>.Enumerator enumerator = this.GetEnumerator();


                if( this.Count == 0 )
                {
                    //writer.WriteEndDocument();
                    return;
                }

                while( enumerator.MoveNext() )
                {
                    KeyValuePair<KeyType, ValueType> keyValuePair = enumerator.Current;

                    writer.WriteStartElement( keyValuePair.Key.ToString() );

                    if( keyValuePair.Value is IXmlSerializable )
                        ((IXmlSerializable)keyValuePair.Value).WriteXml( writer );
                    else
                        //writer.WriteAttributeString( "value", keyValuePair.Value.ToString() );
                        writer.WriteString( keyValuePair.Value.ToString() );

                    writer.WriteEndElement();
                }
            }

            public string ToString( XmlSerializer xmlSerializer )
            {
                StringBuilder buffer = new StringBuilder();
                XmlWriter xmlWriter = XmlWriter.Create( buffer );
                xmlSerializer.Serialize( xmlWriter, this );
                xmlWriter.Close();

                string results = buffer.ToString();
                return results.Substring( results.IndexOf( ">" ) + 1 );
            }

        #endregion

        #region - Base Class Overrides -

            public override string ToString()
            {
                return ToString( new XmlSerializer( typeof( XmlSerializableDictionary<KeyType, ValueType> ) ) );
            }

        #endregion
    }
}

